/*!
 * \file animation_impl.cpp - see common.hpp for copyright info.
 */

#include "common.hpp"

/******************************************************************************/
/*! @brief Create a new animation from the specified image with the specified
 * number of frames.
 *
 * @note Frames should be laid out horizontally at regular intervals in the
 * source image.
 */
ANIMATION::ANIMATION(const char *image_filename, int num_frames)
{
    texture = APP::load_texture(image_filename);
    this->num_frames = num_frames;
}

/******************************************************************************/
/*! @brief Discards the texture for this animation, then frees the animation
 * itself.
 */
ANIMATION::~ANIMATION()
{
    APP::unload_texture(&texture);
}

/******************************************************************************/
/*! @brief Paints the specified frame of the animation at <i>x, y</i> and
 * with <i>size, size</i> dimensions, and rolled <i>angle</i> degrees.
 * If drawn in perspective mode, will automatically turn to face the camera.
 *
 * @param x The x-coordinate to place this animation at in 3D space.
 * @param y The y-coordinate to place this animation at in 3D space.
 * @param z The z-coordinate to place this animation at in 3D space.
 * @param size How many units across the next frame should be when drawn; in
 *  ortho mode, one unit can be considered equivalent to one pixel.
 * @param frame The frame in the animation to draw (numbered from zero to 255).
 * @param angle An amount to rotate the current frame by about its own centre,
 *  given in degrees.
 */
void ANIMATION::paint(float x, float y, float z, float size, float angle, unsigned char frame)
{
    float width_of_frame;

    // slide the texture coordinates across to the appropriate frame...
    glMatrixMode(GL_TEXTURE);
    glPushMatrix();
    width_of_frame = 1.0f/(float)num_frames;
    glScalef(width_of_frame, 1.0f, 1.0f);
    glTranslatef(frame, 0, 0);

    // move to where we want to be in the scene...
    glMatrixMode(GL_MODELVIEW);
    glPushMatrix();
    glTranslatef(x,y,z);
    glRotatef(angle, 0, 0, 1);

    // we already translated it above, so don't do it again...
    APP::draw_sprite(texture, 0, 0, 0, size);

    // put the matrices back like we found them.
    glMatrixMode(GL_TEXTURE);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}

/******************************************************************************/
/*! @brief Paints the specified frame of the animation at <i>x, y</i> and
 * with <i>size, size</i> dimensions with the specified blending mode.
 */
void ANIMATION::paint(float x, float y, float z, float size, float angle, unsigned char frame,
    BLEND_MODE blend_mode)
{
    glEnable(GL_BLEND);

    switch (blend_mode)
    {
        case ADDITIVE:
            glBlendFunc(GL_SRC_COLOR, GL_ONE);
        break;

        case SUBTRACTIVE:
            glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
        break;

        case ALPHA:
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        break;
    }

    paint(x, y, z, size, angle, frame);
    glDisable(GL_BLEND);
}
